﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CodeAnnotationDaemon.cs" company="Jakob Christensen">
//   Copyright (C) by Jakob Christensen
// </copyright>
// <summary>
//   Defines the <see cref="DocumentThrownExceptionDaemon" /> class.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace AgentJohnson.CodeAnnotations
{
  using AgentJohnson.DocumentThrownExceptions;
  using AgentJohnson.Options;
  using JetBrains.Annotations;
  using JetBrains.Application.Settings;
  using JetBrains.ProjectModel;
  using JetBrains.ReSharper.Psi.Tree;
  using Resharper.Abstractions.CodeAnnotations;
  using Resharper.Abstractions.CodeDom.TreeNodes;
  using Resharper.Abstractions.CodeDom.TypeMembers.Constructors;
  using Resharper.Abstractions.CodeDom.TypeMembers.Indexers;
  using Resharper.Abstractions.CodeDom.TypeMembers.Methods;
  using Resharper.Abstractions.CodeDom.TypeMembers.Properties;
  using Resharper.Abstractions.Daemons;

  /// <summary>
  /// Defines the <see cref="DocumentThrownExceptionDaemon"/> class.
  /// </summary>
  [DaemonStage]
  public class CodeAnnotationDaemon : CodeAnnotationDaemonBase
  {
    #region Methods

    /// <summary>Pres the execute.</summary>
    /// <param name="file">The file.</param>
    /// <param name="settings">The settings.</param>
    protected override void PreExecute(IFile file, IContextBoundSettingsStore settings)
    {
      var s = settings.GetKey<AgentJohnsonSettings>(SettingsOptimization.OptimizeDefault);

      this.PublicAssertionCode = s.PublicAssertion ?? string.Empty;
      this.NonPublicAssertionCode = s.NonPublicAssertion ?? string.Empty;

      base.PreExecute(file, settings);
    }

    /// <summary>
    /// Processes the specified tree node.
    /// </summary>
    /// <param name="treeNode">
    /// The tree node.
    /// </param>
    protected override void Process([NotNull] TreeNode treeNode)
    {
      CodeAnnotationModel model = null;

      Property property = null;
      Constructor constructor = null;
      Indexer indexer = null;

      var method = treeNode.GetMethod();
      if (method != null)
      {
        model = new CodeAnnotationModel(this.PublicAssertionCode, this.NonPublicAssertionCode);
        model.Inspect(method);
      }

      if (model == null)
      {
        property = treeNode.GetProperty();
        if (property != null)
        {
          model = new CodeAnnotationModel(this.PublicAssertionCode, this.NonPublicAssertionCode);
          model.Inspect(property);
        }
      }

      if (model == null)
      {
        constructor = treeNode.GetConstructor();
        if (constructor != null)
        {
          model = new CodeAnnotationModel(this.PublicAssertionCode, this.NonPublicAssertionCode);
          model.Inspect(constructor);
        }
      }

      if (model == null)
      {
        indexer = treeNode.GetIndexer();
        if (indexer != null)
        {
          model = new CodeAnnotationModel(this.PublicAssertionCode, this.NonPublicAssertionCode);
          model.Inspect(indexer);
        }
      }

      if (model == null || model.IsAnnotated)
      {
        return;
      }

      var highlight = this.CreateHighlight<CodeAnnotationHighlight>();
      highlight.Model = model;

      if (method != null)
      {
        highlight.Range = method.GetRange();
      }
      else if (property != null)
      {
        highlight.Range = property.GetRange();
      }
      else if (constructor != null)
      {
        highlight.Range = constructor.GetRange();
      }
      else
      {
        highlight.Range = indexer.GetRange();
      }
    }

    #endregion
  }
}